home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
pascal
/
tpsqapi1.zip
/
SQUISH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-02-13
|
28KB
|
900 lines
(*--------------------------------------------------------------------------
SQUISH PASCAL BASED API
version 1.0
(c) copyright 1988-91 Santronics Software
Portions of the code is copyrighted by Alternative Unlimited Inc.
DISCLAIMER: Alternative Unlimited Inc and Santronics Software makes no
warrantly to the accuracy of these functions and data types. We take no
responsibility in their usage. You as a programmer is RESPONSIBLE for
the usage of this library.
NOTES:
If you want voice SUPPORT for this library, you will have to pay for
our time. We charge $65 per hour. All Major Credit Cards Accepted.
Please do not use the Silver Xpress National Support Conferences for
reporting any bugs with this API. Netmail is preferred to either
1:129/82 or 1:290/4.
There are two places where I see MAX has a potentially dynamic record
lengths. The BASE RECORD and the FRAME RECORD. It is important you are
aware of these so that future enhancements to your program will be
compatible with new MAX changes to the squish files. When a squish file
SQD is open, you should call SQSetSQBSize to reset the SQBSIZE variable
to proper the length, and when do you read in the BASE RECORD, set the
SBFSIZE variable to the value defined in the base record. Doing so,
will atleast conform to the way MAX today is setup for the future
changes in the base structure.
There is no critical error trap routines here. It is your programming
responsibility to TRAP and CLOSE, and especially UNLOCK any open SQUISH
file if a critical error occurs. There is a local unit variable
_SQD_FILE_LOCKED which is used here to determine if a message based is
locked when a closing function is called. It is suggested that you test
for this variable's logical state in your critical error trap routine.
----------------------------------------------------------------------------*)
{$A- Use BYTE ALIGHMENT ONLY!!!!!!!!!!!!}
{$O+ Make it OVERLAY ready. DONT FORGET TO FORCE FAR CALLS W/ COMPILER SWITCH}
{$I- No TURBO io file checking. You're on your own}
{$X+ Use EXTENDED calls, ala C. Functions do not need return assignments}
{$V- ignore string parameter passing length checking}
{$IFDEF DEBUG} (* DEVELOPMENT CODE ONLY *)
{$D+ DEBUG INFO}
{$L+ LOCAL SYMBOLS}
{$R- NO RANGE CHECKING BECAUSE OF DYNAMIC ARRAYS BELOW}
{$S+ STACK CHECKING}
{$ELSE} (* PRODUCTION CODE ONLY *)
{$D- NO DEBUG INFO}
{$L- NO LOCAL SYMBOLS}
{$R- NO RANGE CHECKING}
{$S- NO STACK CHECKING}
{$ENDIF}
UNIT SQUISH;
(**************************************************************************
Description:
Squish has four files:
*.SQL - the lastread pointers are stored for the user. The lastus00.dat
file has the user's record number. Seek to it and read a word
to get lastread value for the user for the message base.
*.SQI - is a index of LIVE MESSAGES in the Squish *.SQD file. It
basically stores the 'unique' message id for each message,
the offset of the SQUISH messahe header (sqhdr) and the
HASH of the TOWHOM user's name.
*.SQD - has all the mail. The basic layout is:
BASE_RECORD
then for each message
SQUISH MESSAGE HEADER
CONTROL INFORMATION Where all ^A stuff is stored
TEXT MESSAGE may not always be null terminated
The base record will tell you where the first squish msg header
is at, and each msg header will point to the next or prev one.
In addition, the base record also will point to the first FREE
(one that was marked deleted) Squish Message Header and so on.
So from the base record, you can get a "Doublely linked list"
of both the live messages and free messages.
*.SQB - something to do with dupe checking and I think it's for the
squish mail processor. Not discussed or used in the this API.
*****************************************************************************)
INTERFACE
Uses
crt, (* only used for the DELAY() function *)
Dos, (* Turbo's DOS library *)
iofiles, (* Santronics stream I/O functions *)
strlib, (* Santronics String Library *)
fidofmt; (* your basic SDM (*.MSG) header format *)
TYPE
UMSGID_TYPE = longint;
RECPOS_TYPE = longint;
_Address = record zone,net,node,point : Word end;
MsgBufType = Array[0..0] of Char;
MsgBufPtrtype = ^MsgBufType;
CONST
SQHDRID = $AFAE4453; (* squish headers must have this number *)
LINKNEXT = 0;
LINKPREV = 1;
NULLFRAME = 0;
FRAME_msg = 0; (* it's a live message *)
FRAME_free = 1; (* the message is dead, avail for new msg *)
FRAME_rle = 2; (* type of compression, not implemented *)
FRAME_lzw = 3; (* type of compression, not implemented *)
SQMSG_FROM_SIZE = 36;
SQMSG_TO_SIZE = 36;
SQMSG_SUBJ_SIZE = 72;
MAX_REPLY = 10; (* Max number of stored replies to one msg *)
(* This is the first RECORD in the *.SQD file *)
type _sqbasetype =
record
len : word; (* LENGTH OF THIS STRUCTURE! 0 2 *)
rsvd1 : word; (* Reserved word 2 4 *)
num_msg, (* number of msgs 4 8 *)
high_msg, (* highest msg - always equal to num_msg 8 12 *)
skip_msg: longint; (* # of msgs to keep in beginning of area 12 16 *)
high_water : UMSGID_TYPE; (* High water marker (umsgid) 16 20 *)
uid : UMSGID_TYPE; (* Last usmgid 20 24 *)
base : string[79]; (* Base name for SquishFile 24 104 *)
begin_frame, (* Offset of first frame in file 104 108 *)
last_frame, (* Offset to last frame in file 108 112 *)
first_free, (* Offset of first FREE frame in file 112 116 *)
last_free, (* Ofs of the last free frame 116 120 *)
end_frame : RECPOS_TYPE; (* Pointer to end of file 120 124 *)
max_msg : longint; (* Maximum number of messages 124 128 *)
keep_days : word; (* Max age of messages 128 130 *)
sz_sqhdr : word; (* Size of fram header 130 132 *)
rsvd2 : array[1..124] of byte (* Reserved area 132 256 *)
end;
(*
After thge BASE record, follows a frame record for EACH message. The
begin_frame in the base should point to the first frame header, and
the next_frame in the frame header should point to the next one, etc.
*)
type _sqfhdrtype =
record
id : longint; (* sqhdr.id must always equal SQHDRID *)
next_frame, (* pointer to next msg in base *)
prev_frame : RECPOS_TYPE; (* pointer to prior msg in base *)
frame_length, (* length of this frame (not counting header) *)
msg_length, (* length of msg in frame. may be less than
frame_length if this frame has been recycled. *)
clen : longint; (* Length of the control information. *)
frame_type : word; (* Either FRAME_MESSAGE or FRAME_FREE. The API
has been designed to allow things such
as FRAME_LZSS or FRAME_LZH to be hacked on
later, without changing the application. *)
rsvd : word; (* Reserved *)
end;
(*
But right after each frame header, follows the squish message header,
then the control info, then the text.
*)
type _sqmhdrtype =
record
attr : longint;
fromwhom : string[SQMSG_FROM_SIZE-1];
towhom : string[SQMSG_TO_SIZE-1];
subj : string[SQMSG_SUBJ_SIZE-1];
orig,
dest : _ADDRESS; (* Origination and destination addresses *)
date_written, (* When user wrote the msg (UTC) *)
date_arrived : longint; (* When msg arrived on-line (UTC) *)
utc_ofs : word; (* Minutes offset from UTC of message writer *)
replyto : UMSGID_TYPE;
replies : array[1..MAX_REPLY] of UMSGID_TYPE;
azdate : string[19]; (* ASCII date *)
end;
(*
Each SQD file has a SQI FILES. The message number YOU see (the user)
in MAX is really the counter starting from 1 of each record in SQI.
But the TRUE UNIQUE Message ID is in umsgid. The ofs value will
point to the frame header in SQD. These files are small and you
may read them into a array SqiPtrArrayType using the functions
below.
*)
type _sqidxtype = record
ofs : RECPOS_TYPE; (* Offset of frame header *)
umsgid : UMSGID_TYPE; (* Unique message identifier *)
hash : longint; (* 'To' name hash value *)
end;
SqiPtrArraytype = Array[1..1] of _sqidxtype;
Sqiptrtype = ^sqiptrarraytype;
(*
Sizes of various structures. WARNING, alot of the routines use these
variables. You should be more dynamic and reading the true sizes SCOTT
puts in the squish structures (if any).
*)
CONST
_SQBSIZE : word = SizeOf(_sqbasetype);
_SQFSIZE : word = SizeOf(_sqfhdrtype);
_SQMSIZE : word = SizeOf(_sqmhdrtype);
_SQISIZE : word = SizeOf(_sqidxtype);
_SDMSIZE : word = SizeOf(_fidomsgtype);
(*
Function Prototypes in this unit.
*)
function SqSetSQBSize(var fd: File): Integer;
function SqOpenSQD(name: String; var fd: File; Lock : boolean): Integer;
function SqCloseSQD(var fd: File): Integer;
function SqReadBHdr(var fd: File; var sb: _sqbasetype): Integer;
function SqWriteBHdr(var fd: File; var sb: _sqbasetype): Integer;
function SqReadFHdr(var fd: File; var sf: _sqfhdrtype; fp: LongInt): Integer;
function SqWriteFHdr(var fd: File; var sf: _sqfhdrtype; fp: LongInt): Integer;
function SqReadMHdr(var fd: File; var sm: _sqmhdrtype; fp: LongInt): Integer;
function SqWriteMHdr(var fd: File; var sm: _sqmhdrtype; fp: LongInt): Integer;
function SqReadMTxt(var fd: File; var st; fp: LongInt; ml: LongInt): Integer;
function SqWriteMTxt(var fd: File; var st; fp: LongInt; ml: LongInt): Integer;
function SqOpenSQI(name: String; var fd: File): Integer;
function SqCloseSQI(var fd: File): Integer;
function SqReadSQI(var fd: File; var si: _sqidxtype; fp: LongInt): Integer;
function SqWriteSQI(var fd: File; var si: _sqidxtype; fp: LongInt): Integer;
function SDMRead(name: String; var mh: _fidomsgtype; var mb: MsgBufPtrtype; var mz: LongInt): Integer;
function SqUnlinkFrame(var fd: File; var sf: _sqfhdrtype): Integer;
function SqLinkFrame(var fd: File; var sf: _sqfhdrtype; tp, lp: LongInt; op: Word): Integer;
function SqFreeFrame(var fd: File; var sb: _sqbasetype; rp: LongInt): Integer;
function SqFindFrame(var fd: File; var sb: _sqbasetype; var fl, rp: LongInt): Integer;
function SqNewFrame(var fd: File; var sb: _sqbasetype; var sf: _sqfhdrtype; var ml, rp: LongInt): Integer;
function SqReplaceFrame(var fd: File; var sb: _sqbasetype; var sf: _sqfhdrtype; var rp, ml: LongInt): Integer;
function SqAzHashName(var s): LongInt;
function SqHashName (name : str35) : longint;
Procedure SquishSQIPtr(var sqiptr : sqiptrtype; fn :Pathstr; var sqisize : longint);
function SquishMsgnToUid(var sqiptr : sqiptrtype; Msgn : word ; totalsqi : word) : longint;
function SquishUidToMsgn(var sqiptr : sqiptrtype; uid : longint; totalsqi : word) : word;
function GetSquishBaseRec(fn : pathstr; var sqbaserec : _sqbasetype) : integer;
Function SetSquishMsgAttribute
(
var fvsqd : file;
var fpos : longint;
newattr : longint
) : integer;
implementation
(* Open a "*.SQD" file *)
CONST _SQD_FILE_LOCKED : BOOLEAN = FALSE; (* DONT FUSS WITH THIS VARIABLE *)
function SqOpenSQD(name: String; var fd: File; lock : boolean): Integer;
var
r : Integer;
ax : integer;
Cnt : Integer;
begin
r := Fopen(fd,ForceExtension(name,'SQD'),_READWRITE+_DENYNONE);
ax := r;
if (r = 0) and lock and (not _SQD_FILE_LOCKED) then
begin
Cnt := 1500;
repeat
if not FileLock(FileRec(fd).handle,LockRegion,0,1,ax) then
begin
case ax of
33, (* lock voilation *)
32, (* share voilation *)
5, (* access denied *)
167 (* hardware share voilation *)
: Delay(10);
end;
Dec(cnt);
end
else begin
ax := 0;
_SQD_FILE_LOCKED := TRUE;
end;
until (Cnt=0) or (ax=0);
end;
SqOpenSQD := ax;
end;
(* Close a "*.SQD" file *)
function SqCloseSQD(var fd: File): Integer;
var
r: Integer;
ax : integer;
begin
r := 5;
if _SQD_FILE_LOCKED then
if Not FileLock(FileRec(fd).handle,UnLockRegion,0,1,ax)
Then WRITELN(#13#10'>>ERR#',ax,' :FAILED TO UNLOCK ',Mat2Str(FileRec(fd).Name,50))
else _SQD_FILE_LOCKED := FALSE;
r := fclose(fd);
SqCloseSQD := r
end;
(* Read any data from a "*.SQD" file *)
function SqReadData(var fd: File; var da; fp: LongInt; sz: Word): Integer;
var
r: Integer;
begin
Seek(fd,fp);
r := IoResult;
if (r = 0) then
begin
BlockRead(fd,da,sz,r);
r := IoResult
end;
SqReadData := r
end;
(* Write any data to a "*.SQD" file *)
function SqWriteData(var fd: File; var da; fp: LongInt; sz: Word): Integer;
var
r: Integer;
begin
Seek(fd,fp);
r := IoResult;
if (r = 0) then
begin
BlockWrite(fd,da,sz,r);
r := IoResult
end;
SqWriteData := r
end;
(* Read a "*.SQD" base header. MAKE SURE SQBSIZE IS SET CURRENTLY FOR
THE VERSION MAX *)
function SqReadBHdr(var fd: File; var sb: _sqbasetype): Integer;
begin
SqReadBHdr := SqReadData(fd,sb,0,_SQBSIZE)
end;
(*
Read a "*.SQD" base header structure SIZE. Once you call the SqOPENSQB
you should call this function to make sure the SQBSIZE variable is
current.
*)
function SqSetSQBSize(var fd: File): Integer;
begin
SqSetSQBSize := SqReadData(fd,_SQBSIZE,0,sizeof(word))
end;
(* Write a "*.SQD" base header *)
function SqWriteBHdr(var fd: File; var sb: _sqbasetype): Integer;
begin
SqWriteBHdr := SqWriteData(fd,sb,0,_SQBSIZE)
end;
(* Read a "*.SQD" frame header *)
function SqReadFHdr(var fd: File; var sf: _sqfhdrtype; fp: LongInt): Integer;
begin
SqReadFHdr := SqReadData(fd,sf,fp,_SQFSIZE)
end;
(* Write a "*.SQD" frame header *)
function SqWriteFHdr(var fd: File; var sf: _sqfhdrtype; fp: LongInt): Integer;
begin
SqWriteFHdr := SqWriteData(fd,sf,fp,_SQFSIZE)
end;
(* Read a "*.SQD" message header *)
function SqReadMHdr(var fd: File; var sm: _sqmhdrtype; fp: LongInt): Integer;
begin
SqReadMHdr := SqReadData(fd,sm,fp+_SQFSIZE,_SQMSIZE)
end;
(* Write a "*.SQD" message header *)
function SqWriteMHdr(var fd: File; var sm: _sqmhdrtype; fp: LongInt): Integer;
begin
SqWriteMHdr := SqWriteData(fd,sm,fp+_SQFSIZE,_SQMSIZE)
end;
(* Read a "*.SQD" message text *)
function SqReadMTxt(var fd: File; var st; fp: LongInt; ml: LongInt): Integer;
begin
SqReadMTxt := SqReadData(fd,st,fp+_SQFSIZE+_SQMSIZE,ml-_SQMSIZE)
end;
(* Write a "*.SQD" message text *)
function SqWriteMTxt(var fd: File; var st; fp: LongInt; ml: LongInt): Integer;
begin
SqWriteMTxt := SqWriteData(fd,st,fp+_SQFSIZE+_SQMSIZE,ml-_SQMSIZE)
end;
(* Open a "*.SQI" file *)
function SqOpenSQI(name: String; var fd: File): Integer;
begin
SqOpenSQI := fopen(fd,ForceExtension(name,'SQI'),_READWRITE+_DENYNONE);
end;
(* Close a "*.SQI" file *)
function SqCloseSQI(var fd: File): Integer;
begin
SqCloseSqI := fclose(fd);
end;
(* Read a "*.SQI" index record *)
function SqReadSQI(var fd: File; var si: _sqidxtype; fp: LongInt): Integer;
var
r: Integer;
begin
Seek(fd,fp*_SQISIZE);
r := IoResult;
if (r = 0) then
begin
BlockRead(fd,si,_SQISIZE,r);
r := IoResult
end;
SqReadsqi := r
end;
(* Write a "*.SQI" index record *)
function SqWriteSQI(var fd: File; var si: _sqidxtype; fp: LongInt): Integer;
var
r: Integer;
begin
Seek(fd,fp*_SQISIZE);
r := IoResult;
if (r = 0) then
begin
BlockWrite(fd,si,_SQISIZE,r);
r := IoResult
end;
SqWritesqi := r
end;
(* Open and read a "*.MSG" file *)
function SDMRead(name: String; var mh: _fidomsgtype; var mb: MsgBufptrType; var mz: LongInt): Integer;
var
rc: Integer;
br: Word;
fd: File;
begin
Assign(fd,name);
Reset(fd,1);
rc := IoResult;
mb := NIL;
if (rc = 0) then
begin
BlockRead(fd,mh,_SDMSIZE,br);
mz := FileSize(fd) - _SDMSIZE;
GetMem(mb,mz);
BlockRead(fd,mb^,mz,br);
if (mb^[br] <> #0) then mb^[br] := #0; (* Force a null terminator *)
Close(fd)
end;
SDMread := rc
end;
(* Unlink a frame from the chain *)
function SqUnlinkFrame(var fd: File; var sf: _sqfhdrtype): Integer;
var
r: Integer;
sh: _sqfhdrtype;
begin
r := 0;
if (sf.prev_frame <> 0) then
begin
r := SqReadFHdr(fd,sh,sf.prev_frame);
if (r = 0) then
begin
sh.next_frame := sf.next_frame;
r := SqWriteFHdr(fd,sh,sf.prev_frame)
end
end;
if ((r = 0) and (sf.next_frame <> 0)) then
begin
r := SqReadFHdr(fd,sh,sf.next_frame);
if (r = 0) then
begin
sh.prev_frame := sf.prev_frame;
r := SqWriteFHdr(fd,sh,sf.next_frame)
end
end;
SqUnlinkFrame := r
end;
function SqLinkFrame(var fd: File; var sf: _sqfhdrtype; tp, lp: LongInt; op: Word): Integer;
var
r: Integer;
nxt: LongInt;
sh: _sqfhdrtype;
begin
r := 0;
if (tp <> NULLFRAME) then
begin
r := SqReadFHdr(fd,sh,tp);
if (r = 0) then
begin
if (op = LINKNEXT) then
begin
sf.prev_frame := tp;
nxt := sh.next_frame;
sh.next_frame := lp
end
else
begin
sf.next_frame := tp;
nxt := sh.prev_frame;
sh.prev_frame := lp
end;
r := SqWriteFHdr(fd,sh,tp);
tp := nxt
end;
if ((r = 0) and (tp <> NULLFRAME)) then
begin
r := SqReadFHdr(fd,sh,tp);
if (r = 0) then
begin
if (op = LINKNEXT) then
begin
sh.prev_frame := lp;
sf.next_frame := tp
end
else
begin
sf.prev_frame := tp;
sh.next_frame := lp
end;
r := SqWriteFHdr(fd,sh,tp)
end
end
end;
SqLinkFrame := r
end;
function SqRelinkFrame(var fd: File; var sf: _sqfhdrtype; rp: LongInt): Integer;
var
r: Integer;
begin
if (sf.next_frame = NULLFRAME) then
r := SqLinkFrame(fd,sf,sf.prev_frame,rp,LINKNEXT)
else
r := SqLinkFrame(fd,sf,sf.next_frame,rp,LINKPREV);
SqRelinkFrame := r
end;
function SqFreeFrame(var fd: File; var sb: _sqbasetype; rp: LongInt): Integer;
var
r: Integer;
sqn,
sqn1: _sqfhdrtype;
begin
r := SqReadFHdr(fd,sqn,rp);
if (r = 0) then
begin
r := SqUnlinkFrame(fd,sqn);
if (r = 0) then
begin
if (sb.begin_frame = rp) then
sb.begin_frame := sqn.next_frame;
if (sb.last_frame = rp) then
sb.last_frame := sqn.prev_frame;
sqn.frame_type := Word(FRAME_free);
if (sb.first_free = NULLFRAME) then
begin
sb.first_free := rp;
sb.last_free := rp;
sqn.prev_frame := NULLFRAME;
sqn.next_frame := NULLFRAME
end
else
begin
r := SqReadFHdr(fd,sqn1,sb.last_free);
if (r = 0) then
begin
sqn1.next_frame := rp;
r := SqWriteFHdr(fd,sqn1,sb.last_free);
sqn.prev_frame := sb.last_free;
sqn.next_frame := NULLFRAME
end
end;
if (r = 0) then
begin
sb.last_free := rp;
r := SqWriteFHdr(fd,sqn,rp)
end
end
end;
SqFreeFrame := r
end;
function SqFindFrame(var fd: File; var sb: _sqbasetype; var fl, rp: LongInt): Integer;
var
r: Integer;
sqn: _sqfhdrtype;
break: Boolean;
begin
r := 0;
break := FALSE;
rp := sb.first_free;
while ((rp > NULLFRAME) and (not break)) do
begin
r := SqReadFHdr(fd,sqn,rp);
if ((r = 0) and (fl < sqn.frame_length)) then
break := TRUE
else
rp := sqn.next_frame
end;
if (r = 0) then
begin
if (rp = NULLFRAME) then
begin
fl := 0;
rp := sb.end_frame
end
else
begin
r := SqUnlinkFrame(fd,sqn);
if (r = 0) then
begin
if (sqn.prev_frame = NULLFRAME) then
sb.first_free := sqn.next_frame;
if (sqn.next_frame = NULLFRAME) then
sb.last_free := sqn.prev_frame;
fl := sqn.frame_length
end
end
end;
SqFindFrame := r
end;
function SqNewFrame(var fd: File; var sb: _sqbasetype; var sf: _sqfhdrtype; var ml, rp: LongInt): Integer;
var
r: Integer;
sqn: _sqfhdrtype;
begin
r := SqFindFrame(fd,sb,ml,rp);
if (r = 0) then
begin
if (sb.last_frame <> NULLFRAME) then
begin
r := SqReadFHdr(fd,sqn,sb.last_frame);
if (r = 0) then
begin
sqn.next_frame := rp;
r := SqWriteFHdr(fd,sqn,sb.last_frame)
end
end
else
sb.begin_frame := rp;
if (r = 0) then
begin
sf.id := SQHDRID;
sf.frame_type := Word(FRAME_msg);
sf.prev_frame := sb.last_frame;
sb.last_frame := rp;
sf.next_frame := NULLFRAME
end
end;
SqNewFrame := r
end;
function SqReplaceFrame(var fd: File; var sb: _sqbasetype; var sf: _sqfhdrtype; var rp, ml: LongInt): Integer;
var
r: Integer;
begin
r := SqReadFHdr(fd,sf,rp);
if (r = 0) then
begin
if (ml > sf.frame_length) then
begin
r := SqFreeFrame(fd,sb,rp);
if (r = 0) then
begin
sf.frame_length := ml;
r := SqFindFrame(fd,sb,sf.frame_length,rp);
if (r = 0) then
begin
if (sf.prev_frame = NULLFRAME) then
sb.begin_frame := rp;
if (sf.next_frame = NULLFRAME) then
sb.last_frame := rp
end
end
end
end;
SqReplaceFrame := r
end;
(* Convert a asciiz username into a hash value for the index. The logic
used in this code (pointer arithmetic) is ok to use because we are
dealing with small lengths and will never exceed 64k.
*)
function SqAzHashName(var s): LongInt;
var
p: ^Char;
g,
hash: LongInt;
begin
hash := 0;
p := @s;
while (p^ <> #0) do
begin
hash := (hash shl 4) + Byte(locase(p^));
g := (hash and $f0000000);
if (g <> 0) then
begin
hash := (hash or (g shr 24));
hash := (hash or g)
end;
Inc(LongInt(p))
end;
SqAzHashName := (hash and $7fffffff)
end;
(* Convert a Pascal username into a hash value for the index.
*)
function SqHashName (name : str35) : longint;
var p : integer;
hash,g : longint;
begin
hash := 0;
for p := 1 to length(name) do
begin
hash := (hash shl 4) + ord(locase(name[p]));
g := hash and $F0000000;
if (g <> 0) then
begin
hash := hash or (g shr 24);
hash := hash or g;
end;
end;
SqHashName := hash and $7fffffff;
end;
(*
The following functions are used convert back and forth between between
the msg number and the unique msg id in the sqi files. You should use
these for lastread pointers, reply links, etc.
*)
function SquishUidToMsgn(var sqiptr : sqiptrtype; uid : longint; totalsqi : word) : word;
var idx : word;
begin
SquishUidToMsgn := 0;
if (sqiptr <> NIL) and (totalsqi > 0) and (uid > 0) then
begin
idx := 1;
while (uid > sqiptr^[idx].umsgid) and ((Idx) <= totalsqi) do inc(idx);
if idx > totalsqi then Idx := TotalSqi;
SquishUidToMsgn := idx;
end;
end;
function SquishMsgnToUid(var sqiptr : sqiptrtype; Msgn : word ; totalsqi : word) : longint;
begin
SquishMsgnToUid := 0;
if (sqiptr <> NIL) and (TotalSqi > 0) then
begin
if Msgn > totalSqi then Msgn := totalsqi;
if Msgn = 0 then Msgn := 1;
SquishMsgnToUid := sqiptr^[msgn].umsgid;
end;
end;
(*
Open SQI file and read in the entire file. This is your INDEX system
to the SQD files. Once in memory, you can cycle thru this list by
msg #, UID # or user name (hash) and get the offset to the Squish header
record in the SQD file. (Double check the SQHDR_ID value to make sure
the record is valid).
ie, Var sqiptr : sqpptrtype;
sqisize : longint;
actrecs : word;
SquishSQIPtr(sqiptr,'XPRESS.SQI',sqisize);
actrecs := sqisize div _SQISIZE;
.
.
.
FreeMem(sqiptr,sqisize);
Don't forget to FREE the the Sqiptr pointer variable using the sqisize
passed.
*)
Procedure SquishSQIPtr(var sqiptr : sqiptrtype; fn :Pathstr; var sqisize : longint);
var fv : stream;
abytes : word;
begin
SqiPtr := NIL;
sqisize := 0;
if fopen(fv,fn,_READONLY+_DENYNONE) <> 0 then exit;
sqisize := filesize(fv);
if sqisize = 0 then
begin
fclose(fv);
exit;
end;
GetMem(sqiptr,sqisize);
if sqiptr <> NIL then Blockread(fv,sqiptr^,sqisize,abytes);
fclose(fv);
end;
function GetSquishBaseRec(fn : pathstr; var sqbaserec : _sqbasetype) : integer;
var fv : stream;
ax : integer;
ab : word;
begin
ax := fopen(fv,fn,_READONLY+_DENYNONE);
GetSquishBaseRec := ax;
if ax = 0 then
begin
(* SQ BASE *)
blockread(fv,sqbaserec,_SQBSIZE,ab);
fclose(fv);
end;
end;
(*
Given message frame position, read message header and set the message
attribute bit. The newattr is ORed to the previous value.
*)
Function SetSquishMsgAttribute
(
var fvsqd : file;
var fpos : longint;
newattr : longint
) : integer;
var
xmsg : _sqmhdrtype;
begin
SetSquishMsgAttribute := -1;
if SqReadMhdr(fvsqd,xmsg,fpos) = 0 then
begin
xmsg.attr := xmsg.attr or NEWATTR;
SetSquishMsgAttribute := SqWriteMHdr(fvsqd,xmsg,fpos);
end;
end;
end. (**************************************************** END OF API ****)